package org.mili.ticketeer.dao;

import org.mili.application.dao.AbstractDao;
import org.mili.application.dao.DaoException;
import org.mili.application.dao.ModificationResult;
import org.mili.application.dao.RowTransformer;
import org.mili.application.dao.query.QueryBuilder;
import org.mili.ticketeer.dto.Contact;
import org.mili.ticketeer.dto.ContactMeeting;
import org.mili.application.dto.Identifieable;
import org.mili.ticketeer.dto.Meeting;
import org.mili.application.util.Lambda;

import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Timestamp;
import java.util.List;

public class MeetingDao extends AbstractDao {

    public MeetingDao() {
        super(Meeting.Fields.values(), Meeting.Fields.values(), Meeting.TABLE);
    }

    public List<Meeting> getMeetings() throws DaoException {
        return doInDao(new Lambda<List<Meeting>>() {
            @Override
            public List<Meeting> exec(Object... params) throws Exception {
                return read(meetingRowTransformer,
                        QueryBuilder.createQueryBuilder()
                            .select()
                            .fields(Identifieable.Fields.ID, fields)
                            .from(table)
                            .orderBy().desc(Meeting.Fields.DATE)
                            .build());

            }
        });
    }

    private RowTransformer<Meeting> meetingRowTransformer = new RowTransformer<Meeting>() {
                        @Override
                        public Meeting transform(ResultSet resultSet) throws SQLException {
                            Meeting meeting = new Meeting();
                            meeting.setId(resultSet.getInt(Identifieable.Fields.ID.name()));
                            meeting.setDate(resultSet.getTimestamp(Meeting.Fields.DATE.name()));
                            return meeting;
                        }
                    };

    public Meeting findMeetingByDate(final Timestamp timestamp) throws DaoException {
        return doInDao(new Lambda<Meeting>() {
            @Override
            public Meeting exec(Object... params) throws Exception {
                return (Meeting) readSingle(meetingRowTransformer, QueryBuilder.createQueryBuilder()
                        .select()
                        .fields(Identifieable.Fields.ID, Meeting.Fields.values())
                        .from(Meeting.TABLE)
                        .where()
                        .eq(Meeting.Fields.DATE, timestamp)
                        .build());
            }
        });
    }

    public List<ContactMeeting> getVisitedMeetingsFor(final Contact contact) throws DaoException {
        return doInDao(new Lambda<List<ContactMeeting>>() {
            @Override
            public List<ContactMeeting> exec(Object... params) throws Exception {
                return read(new RowTransformer<ContactMeeting>() {
                    @Override
                    public ContactMeeting transform(ResultSet resultSet) throws SQLException {
                        ContactMeeting contactMeeting = new ContactMeeting();
                        contactMeeting.setMeeting(resultSet.getInt(ContactMeeting.Fields.MEETING.name()));
                        contactMeeting.setContact(contact.getId());
                        return contactMeeting;
                    }
                }, QueryBuilder.createQueryBuilder()
                        .select()
                        .fields(ContactMeeting.Fields.values())
                        .from(ContactMeeting.TABLE)
                        .where()
                        .eq(ContactMeeting.Fields.CONTACT, contact.getId())
                        .build());
            }
        });
    }

    public ModificationResult write(Meeting meeting) throws DaoException {
        return createOrUpdate(meeting);
    }

    public Meeting getMeetingById(final int id) throws DaoException {
        return doInDao(new Lambda<Meeting>() {
            @Override
            public Meeting exec(Object... params) throws Exception {
                return (Meeting) readSingle(meetingRowTransformer, QueryBuilder.createQueryBuilder()
                        .select()
                        .fields(Identifieable.Fields.ID, Meeting.Fields.values())
                        .from(Meeting.TABLE)
                        .where()
                        .eq(Identifieable.Fields.ID, id)
                        .build());
            }
        });
    }
}
